package com.mixed.mixedserver.game.network;

import com.mixed.mixedserver.config.NettyConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import jakarta.annotation.PreDestroy;

@Component
public class GameNettyServer implements CommandLineRunner {
    private static final Logger logger = LoggerFactory.getLogger(GameNettyServer.class);
    
    @Resource
    private NettyConfig nettyConfig;
    
    @Resource
    private GameChannelInitializer channelInitializer;
    
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private ChannelFuture channelFuture;
    
    @Override
    public void run(String... args) {
        startServer();
    }
    
    public void startServer() {
        try {
            // 创建事件循环组
            bossGroup = new NioEventLoopGroup(nettyConfig.getBossThreads());
            workerGroup = new NioEventLoopGroup(nettyConfig.getWorkerThreads());
            
            // 创建服务器启动器
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(channelInitializer)
                    .option(ChannelOption.SO_BACKLOG, nettyConfig.getSoBacklog())
                    .childOption(ChannelOption.SO_KEEPALIVE, nettyConfig.isSoKeepalive())
                    .childOption(ChannelOption.TCP_NODELAY, nettyConfig.isTcpNodelay());
            
            // 绑定端口并启动服务器
            channelFuture = bootstrap.bind(nettyConfig.getPort()).sync();
            
            logger.info("Netty game server started on port {}", nettyConfig.getPort());
            logger.info("Server configuration: bossThreads={}, workerThreads={}, soBacklog={}", 
                nettyConfig.getBossThreads(), 
                nettyConfig.getWorkerThreads(), 
                nettyConfig.getSoBacklog());
            
            // 在新线程中等待服务器关闭，避免阻塞Spring Boot启动
            new Thread(() -> {
                try {
                    channelFuture.channel().closeFuture().sync();
                } catch (InterruptedException e) {
                    logger.error("Server interrupted", e);
                    Thread.currentThread().interrupt();
                }
            }, "netty-server-closer").start();
            
        } catch (Exception e) {
            logger.error("Failed to start Netty server", e);
            shutdown();
            throw new RuntimeException("Failed to start Netty server", e);
        }
    }
    
    @PreDestroy
    public void shutdown() {
        logger.info("Shutting down Netty game server...");
        
        try {
            if (channelFuture != null) {
                channelFuture.channel().close().sync();
            }
        } catch (InterruptedException e) {
            logger.error("Error closing server channel", e);
            Thread.currentThread().interrupt();
        }
        
        if (workerGroup != null) {
            workerGroup.shutdownGracefully();
        }
        
        if (bossGroup != null) {
            bossGroup.shutdownGracefully();
        }
        
        logger.info("Netty game server shutdown complete");
    }
    
    public boolean isRunning() {
        return channelFuture != null && channelFuture.channel().isActive();
    }
    
    public int getPort() {
        return nettyConfig.getPort();
    }
}